package com.geline.sqlbackup.util;

import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.DbType;
import com.geline.sqlbackup.bean.ColumnInfo;
import com.geline.sqlbackup.bean.TableColumnInfo;
import lombok.extern.slf4j.Slf4j;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据库备份工具类
 * @author: mengx
 * @date: 2021/8/16 9:32
 */
@Slf4j
public class SqlBackupUtils {

    /**
     * 获取所有数据的插入语句
     * @param dataSource
     * @param tableColumnInfo
     * @param showColumns 显示字段
     * @return
     */
    public static String createInsertSql(DataSource dataSource, TableColumnInfo tableColumnInfo, boolean showColumns, String sql){
        StringBuilder sb = new StringBuilder();
        List<ColumnInfo> columnInfoList = tableColumnInfo.getColumnInfoList();
        List<String> columnNames = columnInfoList.stream().map(row -> row.getColumnName()).collect(Collectors.toList());

        List<Map<String, Object>> mapList = SqlRunnerUtils.selectMaps(dataSource, sql);

        if(mapList.size()>0){
            String schemaName = JdbcParseUtils.findSchemaName(dataSource);
            for (Map<String, Object> valueMap : mapList) {
                String insertSql = SqlParseUtils.createInsertOneSql(showColumns, tableColumnInfo, columnNames, valueMap, schemaName);
                sb.append(insertSql).append(";\n");
            }
        }
        return sb.toString();
    }

    /**
     * 获取所有数据的插入语句
     * @param dataSource
     * @param tableColumnInfo
     * @param showColumns 显示字段
     * @return
     */
    public static String createInsertAllSql(DataSource dataSource, TableColumnInfo tableColumnInfo, boolean showColumns, String whereSql){
        String tableName = tableColumnInfo.getTableName();
        List<ColumnInfo> columnInfoList = tableColumnInfo.getColumnInfoList();
        List<String> columnNames = columnInfoList.stream().map(row -> row.getColumnName()).collect(Collectors.toList());
        whereSql = StrUtil.isBlank(whereSql) ? "" : whereSql;
        // SELECT `index`,create_time FROM table; 关键字index要加＇
        String sql = String.format("SELECT `%s` FROM %s %s", StrUtil.join("`,`", columnNames), tableName, whereSql);
        return createInsertSql(dataSource, tableColumnInfo, showColumns, sql);
    }

    /**
     * 获取导出表结构SQL
     * @param dataSource
     * @param tableNameList
     * @return
     */
    public static String createTableDDLSql(DataSource dataSource, List<String> tableNameList){
        StringBuilder sb = new StringBuilder();
        // 获取生成序列脚本
        String sequenceInfos = DataSourceDdlUtil.parseSequenceDDLs(dataSource);
        if (StrUtil.isNotEmpty(sequenceInfos)) {
            sb.append(sequenceInfos);
        }

        DbType dbType = JdbcDbTypeUtil.getDbTypeOfDruid(dataSource);
        List<String> ddlSqlList = DataSourceDdlUtil.parseTableDDLs(dataSource, tableNameList);
        for(int i=0; i<tableNameList.size(); i++){
            String table = tableNameList.get(i);
            String tableDDL = ddlSqlList.get(i);

            sb.append("-- ----------------------------").append("\n");
            sb.append("-- Table structure for "+table).append("\n");
            sb.append("-- ----------------------------").append("\n");

            if(dbType == DbType.mysql){
                sb.append("DROP TABLE IF EXISTS "+table+";").append("\n");
            } else {
                String schemaName = JdbcParseUtils.findSchemaName(dataSource);
                sb.append("DROP TABLE IF EXISTS " + schemaName + "." + table + ";").append("\n");
            }
            sb.append(tableDDL).append(";\n");
        }
        return sb.toString();
    }

    /**
     * 获取导出表结构+表数据
     * @param dataSource
     * @param tableNameList
     * @param showColumns
     * @param whereSql  举例：where 1=1
     * @return
     */
    public static String createTableDDL2InsertAllSql(DataSource dataSource, List<String> tableNameList, boolean showColumns, String whereSql){
        DbType dbType = JdbcDbTypeUtil.getDbTypeOfDruid(dataSource);
        StringBuilder sb = new StringBuilder();
        // 获取生成序列脚本
        String sequenceInfos = DataSourceDdlUtil.parseSequenceDDLs(dataSource);
        if (StrUtil.isNotEmpty(sequenceInfos)) {
            sb.append(sequenceInfos);
        }

        List<String> ddlSqlList = DataSourceDdlUtil.parseTableDDLs(dataSource, tableNameList);
        for(int i=0; i<tableNameList.size(); i++){
            String table = tableNameList.get(i);
            String tableDDL = ddlSqlList.get(i);

            sb.append("-- ----------------------------").append("\n");
            sb.append("-- Table structure for "+table).append("\n");
            sb.append("-- ----------------------------").append("\n");

            if(dbType == DbType.mysql){
                sb.append("DROP TABLE IF EXISTS "+table+";").append("\n");
            }else {
                String schemaName = JdbcParseUtils.findSchemaName(dataSource);
                sb.append("DROP TABLE IF EXISTS " + schemaName + "." + table + ";").append("\n");
            }
            sb.append(tableDDL).append(";\n");
            log.debug("tableDDL ===== \n{}", tableDDL);
            TableColumnInfo tableColumnInfo = DataSourceDdlUtil.parseTableColumnInfo(dataSource, table, false, true);
            sb.append(createInsertAllSql(dataSource, tableColumnInfo, showColumns, whereSql)).append("\n");
        }
        return sb.toString();
    }
}
